package game;

import org.newdawn.slick.*;

/**
 * Gui Klasse des gesamten Programms.
 * Die Methode init() wird einmal ausgeführt.
 * update() wird in kurzen Zeitabständen ausgeführt und fungiert als Timer für das Spiel. Sie hält das Spiel am laufen
 * render() Zeichnet alle Menüs und das Spiel. Wird in kurzen Abständen hintereinander ausgeführt
 * 
 * @author mariuswi
 * @version 0.1
 * 
 */
public class GameGui extends org.newdawn.slick.BasicGame {
    
    
    //Attribute---------------------------------------------------------------------
    
    private AppGameContainer app;
    private GameControl c;
    private GuiStartmenu startmenu;
    private GuiPlay play;
//    private boolean renderInit = false;
    

    
    
    //MAIN----------------
    /**
     * Main Methode.
     * Erstellt ein neues Gui Fenster und den Container, welcher die Inputs/den Bildschirm verwaltet.
     * @param Args
     * @throws SlickException 
     */
    public static void main(String[] Args  ) throws SlickException{
        GameGui game = new GameGui("Pong Game");
        AppGameContainer app = new AppGameContainer(game);
        game.setApp(app);
        app.start();
       
       
    }
   
    //Methoden----------------------------------------------------------------------
    //Konstruktor---------
    public GameGui(String title){
        super(title);
       
    }
    
    /**
     * Initialisiert die GUI und den Container.
     * Erstellt die Klasse GameControl, die die Aktionen des Spiels steuert.
     * @param container
     * @throws SlickException 
     */
    @Override
    public void init(GameContainer container) throws SlickException {
        
        //Systemeinstellungen einrichten
        container.setMinimumLogicUpdateInterval(5);
        container.setMaximumLogicUpdateInterval(5);
        container.setFullscreen(false);
        container.setShowFPS(true);
        container.setTargetFrameRate(60);
        container.setVSync(true);     
        
        //GameStates und GuiStates instanzieren
        startmenu = new GuiStartmenu();
        startmenu.init(app);
        play = new GuiPlay();
        
        //Spielmechanik instanzieren
        c = new GameControl(this);
        
    }
    /**
     * Macht den Container und die GUI miteinander bekannt.
     * 
     * Zur Verbindungserstellung zwischen der Klasse Game und dem AppGameContainer,
     * welcher genutzt wird. Dadurch kann in der Methode init(...) auf alle Methoden
     * des Containers zugegriffen werden.
     * @param app 
     */
    public void setApp(AppGameContainer app){
        this.app = app;
    }

    /**
     * Wird vor dem Starten eines Spiels ausgeführt, um bei Bedarf nochmal Einstellungen anzupassen
     * 
     * @param width Resolution
     * @param height Resolution
     * @throws SlickException 
     */
    public void setArenaSize(int arenaWidth,int arenaHeight) throws SlickException{
        play.setScreen(this.app, arenaWidth, arenaHeight);
    }
    
//UPDATE METHODE-------------------------------------------------------------------
    /**
     * Wird in kurzen Abständen hintereinander ausgeführt. Hält das Spiel am laufen.
     * Ruft abhängig vom Gamestate() welcher in der GameControl gespeichert ist die unterschiedlichen
     * Update Methoden auf. z.B. c.update() ist die Haupt-Spiel Update Methode
     * 
     * @param container
     * @param delta
     * @throws SlickException 
     */
    @Override
    public void update(GameContainer container, int delta) throws SlickException {
        switch(c.getGamestate()){
            case 1: break;
            case 2: this.getInput(); c.update(); break; // Spiel läuft
            case 8: this.getInput(); break; //Spiel pausiert
            case 10: this.startmenu.update(container, this.c); break; //Startmenü
            default: break; 
                
        }
       
    }  
    
//RENDER-METHODE------------------------------------------------------------------
    /**
     * Rendert das Spiel. Wird in kurzen Abständen hintereinander ausgeführt.
     * Abhängig vom Gamestate, welcher in der GameControl gespeichert ist werden die 
     * Unterschiedlichen Menüs gerendert oder das Hauptspiel
     * 
     * @param container
     * @param g
     * @throws SlickException 
     */
    @Override
    public void render(GameContainer container, Graphics g) throws SlickException {   
                
        switch(c.getGamestate()){
            case 1: break;
            case 2: this.play.render(container, g, c.getDrawables()); break;
            case 8: this.play.render(container, g, c.getDrawables()); break;
            case 10: this.startmenu.render(container, g);break;
                
            default: g.drawString("Unzulässiger Gamestate", 100, 100);
           
              
        }        
    }

    /**
     * Beendet das Spiel. Darf nur von der GameControl aufgerufen werden.
     */
    public void exit(){
        this.app.exit();
    }
    /**
     * Holt sich die Inputs und gibt ein Input Kommando an die GameControl.
     * Die Kommando-Codierung findet sich in der Dokumentation zur Methode incomingInput() der Klasse GameControl
     * 
     */
    private void getInput() throws SlickException {
        Input input = this.app.getInput();
        if(input.isKeyDown(input.KEY_W)){
            c.incomingInput(new CInput(CInput.LEFT,CInput.UP));
        }
        if(input.isKeyDown(input.KEY_S)){
            c.incomingInput(new CInput(CInput.LEFT,CInput.DOWN));
        }
        if(input.isKeyDown(input.KEY_UP)){
            c.incomingInput(new CInput(CInput.RIGHT,CInput.UP));
        }
        if(input.isKeyDown(input.KEY_DOWN)){
            c.incomingInput(new CInput(CInput.RIGHT,CInput.DOWN));
        }
        if(input.isKeyDown(input.KEY_B)){
            c.incomingInput(new CInput(CInput.BOTTOM, CInput.DOWN));
        }
        if(input.isKeyDown(input.KEY_N)){
            c.incomingInput(new CInput(CInput.BOTTOM, CInput.UP));
        }
        if(input.isKeyDown(input.KEY_SPACE)){
            c.incomingInput(new CInput(CInput.PAUSE));
        }
        if(input.isKeyDown(input.KEY_ESCAPE)){
            this.startmenu.init(app);
            c.incomingInput(new CInput(CInput.MENU));
        }
        
    }

}
